pub struct Fingerprint {
extra: String,
deps: Vec<Fingerprint>,
- personal: Personal,
+ local: LocalFingerprint,
}
#[derive(Clone)]
-enum Personal {
- Known(String),
- Unknown(Path),
+enum LocalFingerprint {
+ Precalculated(String),
+ MtimeBased(Option<u64>, Path),
}
impl Fingerprint {
- fn resolve(&self) -> CargoResult<String> {
- let mut deps: Vec<_> = try!(self.deps.iter().map(|s| s.resolve()).collect());
+ fn resolve(&self, force: bool) -> CargoResult<String> {
+ let mut deps: Vec<_> = try!(self.deps.iter().map(|s| {
+ s.resolve(force)
+ }).collect());
deps.sort();
- let known = match self.personal {
- Personal::Known(ref s) => s.clone(),
- Personal::Unknown(ref p) => {
+ let known = match self.local {
+ LocalFingerprint::Precalculated(ref s) => s.clone(),
+ LocalFingerprint::MtimeBased(Some(n), _) if !force => n.to_string(),
+ LocalFingerprint::MtimeBased(_, ref p) => {
debug!("resolving: {}", p.display());
try!(fs::stat(p)).modified.to_string()
}
calculate(cx, p, t, kind)
}).collect::<CargoResult<Vec<_>>>());
- // And finally, calculate what our own personal fingerprint is
- let personal = if use_dep_info(pkg, target) {
+ // And finally, calculate what our own local fingerprint is
+ let local = if use_dep_info(pkg, target) {
let dep_info = dep_info_loc(cx, pkg, target, kind);
- match try!(calculate_target_mtime(&dep_info)) {
- Some(i) => Personal::Known(i.to_string()),
- None => {
- // If the dep-info file does exist (but some other sources are
- // newer than it), make sure to delete it so we don't pick up
- // the old copy in resolve()
- let _ = fs::unlink(&dep_info);
- Personal::Unknown(dep_info)
- }
+ let mtime = try!(calculate_target_mtime(&dep_info));
+
+ // if the mtime listed is not fresh, then remove the `dep_info` file to
+ // ensure that future calls to `resolve()` won't work.
+ if mtime.is_none() {
+ let _ = fs::unlink(&dep_info);
}
+ LocalFingerprint::MtimeBased(mtime, dep_info)
} else {
- Personal::Known(try!(calculate_pkg_fingerprint(cx, pkg)))
+ LocalFingerprint::Precalculated(try!(calculate_pkg_fingerprint(cx, pkg)))
};
let fingerprint = Fingerprint {
extra: extra,
deps: deps,
- personal: personal,
+ local: local,
};
cx.fingerprints.insert(key, fingerprint.clone());
Ok(fingerprint)
let new_fingerprint = Fingerprint {
extra: String::new(),
deps: Vec::new(),
- personal: Personal::Known(new_fingerprint),
+ local: LocalFingerprint::Precalculated(new_fingerprint),
};
let is_fresh = try!(is_fresh(&loc, &new_fingerprint));
fn prepare(is_fresh: bool, loc: Path, fingerprint: Fingerprint) -> Preparation {
let write_fingerprint = Work::new(move |_| {
debug!("write fingerprint: {}", loc.display());
- let fingerprint = try!(fingerprint.resolve().chain_error(|| {
+ let fingerprint = try!(fingerprint.resolve(true).chain_error(|| {
internal("failed to resolve a pending fingerprint")
}));
try!(File::create(&loc).write_str(fingerprint.as_slice()));
};
let old_fingerprint = try!(file.read_to_string());
- let new_fingerprint = match new_fingerprint.resolve() {
+ let new_fingerprint = match new_fingerprint.resolve(false) {
Ok(s) => s,
Err(..) => return Ok(false),
};
-use std::old_io::{fs, File, USER_RWX};
+use std::old_io::{fs, File, USER_RWX, timer};
+use std::time::Duration;
use support::{project, execs, main_file, cargo_dir};
use support::{COMPILING, RUNNING};
//
// We base recompilation off mtime, so sleep for at least a second to ensure
// that this write will change the mtime.
- p.root().move_into_the_past().unwrap();
+ timer::sleep(Duration::seconds(1));
File::create(&p.root().join("baz/src/baz.rs")).write_str(r#"
pub fn baz() { println!("hello!"); }
"#).unwrap();
COMPILING, p.url())));
// Make sure an update to bar doesn't trigger baz
- p.root().move_into_the_past().unwrap();
+ timer::sleep(Duration::seconds(1));
File::create(&p.root().join("bar/src/bar.rs")).write_str(r#"
extern crate baz;
pub fn bar() { println!("hello!"); baz::baz(); }
assert_that(p.process(cargo_dir().join("cargo")).arg("build"),
execs().with_status(0));
});
+
+test!(changing_features_is_ok {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ authors = []
+ version = "0.0.1"
+
+ [features]
+ foo = []
+ "#)
+ .file("src/lib.rs", "");
+
+ assert_that(p.cargo_process("build"),
+ execs().with_status(0)
+ .with_stdout("\
+[..]Compiling foo v0.0.1 ([..])
+"));
+
+ assert_that(p.process(cargo_dir().join("cargo")).arg("build")
+ .arg("--features").arg("foo"),
+ execs().with_status(0)
+ .with_stdout("\
+[..]Compiling foo v0.0.1 ([..])
+"));
+
+ assert_that(p.process(cargo_dir().join("cargo")).arg("build"),
+ execs().with_status(0)
+ .with_stdout("\
+[..]Compiling foo v0.0.1 ([..])
+"));
+
+ assert_that(p.process(cargo_dir().join("cargo")).arg("build"),
+ execs().with_status(0)
+ .with_stdout(""));
+});